/*********************************************************************************
 *      Copyright:  (C) 2025 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(28/03/25)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "28/03/25 21:04:39"
 *                 
 ********************************************************************************/

#include "main.h"

int main(int argc, char **argv)
{
	int                   rv = -1;
	int                   times;
	int                   daemon_run = 0;
	int                   ch;
    int                   sampling;
	int                   time_flag = 0;

	time_t                time_now = 0;
	time_t                time_before = 0;
	char				  buf[1024];
	char				  *hostname = NULL;
	int                   port=0;
	int					  sn = 1;
    int					  len = 0;
	char              	  *progname=NULL;
	int                   g_signal = 0;

	const char            *db = "client.db";
	char                  *logfile = "running_cli.log";
	char                  loglevel = LOG_LEVEL_INFO;

	pack_proc_t          pack_proc = pack_data;
	data_t                data;
	socket_cli            sock;

	memset(&data, 0, sizeof(data));
	memset(&sock, 0, sizeof(sock));

	struct option        opts[] = {
    	{"ip", required_argument, NULL, 'i'},
		{"port", required_argument, NULL, 'p'},
		{"time",  required_argument,  0, 't'},
		{"sn", required_argument, NULL, 's'},
		{"background", no_argument, NULL, 'b'},
		{"debug", no_argument, NULL, 'd'},
		{"version", no_argument, NULL, 'v'},
		{"Pack", required_argument, NULL, 'P'},
		{"Stop", no_argument, NULL, 'S'},
		{"help", no_argument, NULL, 'h'},
		{NULL, 0, NULL, 0}
	};

	progname = (char *)basename(argv[0]);

	while((ch = getopt_long(argc, argv, "i:p:t:s:bdvP:Sh", opts, NULL)) != -1)
	{
		switch(ch)
		{
			case 'i':
				hostname = optarg;
				break;
		
			case 'p':
				port = atoi(optarg);
				break;
			
			case 't':
				times = atoi(optarg);
				break;
			
			case 'b':
				daemon_run = 1;
				break;
    
			case 'd':
				logfile = "stdout";
				loglevel = LOG_LEVEL_DEBUG;
				break;

			case 's':
				sn = atoi(optarg);
				break;

			case 'v':
				dbg_print("%s version %s\n", progname, PROG_VERSION);
				return 0; 

			case 'P':
				if ( strcmp(optarg, "json") == 0 )
				{
					pack_proc = pack_data_json;
				}
				else if ( strcmp(optarg, "tlv") == 0 )
				{
					pack_proc = pack_data_tlv;
				}
				else
				{
					print_usage(argv[0]);
				}
				break;

			case 'S':
				stop_background_running(PIDFILE);
				return 0;

			case 'h':
				print_usage(argv[0]);
				return 0;

			default:
				print_usage(argv[0]);
				return 0;
		}
	}

	if(!socket_init(&sock, hostname, port) )
	{
		print_usage(argv[0]);
		return 0;
	}

	/*日志初始化*/
	if(logger_init(logfile, loglevel) < 0)
	{
		fprintf(stderr, "Initial logger file '%s' failure\n",logfile,strerror(errno));
		log_error("Initial logger system failure\n");
		return -1;
	}
	
	if ( !proc_deamon(daemon_run, PIDFILE) )
	{
		goto Cleanup;
	}

	get_sn(data.sn, sizeof(data.sn)-1, sn);

	/* 安装信号*/
	signal(SIGINT, stop);
	signal(SIGTERM, stop);

	/*数据库初始化*/
	if( database_init(db) < 0)
	{
		log_error("Initial database  failure\n");
		return -2;
	}


	while(! pro_stop)    /*循环，为0的时候执行，刚开始给pro_stop赋值为0*/
	{
		sampling = 0;    /* 没到采样时间*/
		time(&time_now);   /*获取当前时间并存到time_now中 */ 

		if( (time_now - time_before) >= times)    /* 如果到了采样时间*/
		{
			log_info("time reached\n");
			
			/*采温*/ 
			rv = get_temper(&data);   
			if(rv < 0)      /* 采温失败,退出整个循环,再采温*/ 
			{
				log_error("Get temperature failure,return value: %d\n",rv);
				break;
			}

			/*获取时间*/ 
			get_time(&data);
			
			sampling = 1;
			time_flag = 0;
			time_before = time_now;
		}
       
		/* 检测连接状态,函数连接返回0，断开返回-1 */
		if(socket_check(&sock) < 0)  
		{
			if(sock.sockfd > 0)         /*断开连接后sockfd本身值不变，但这个文件描述符已经不能用了，需要关闭 */
			{ 
				close(sock.sockfd);
				log_error("socket disconnected\n");
				dbg_print("Disconnect from the server.\n");
			}	
			rv = socket_connect(&sock);
		}	
		
		if(socket_check(&sock) < 0)   /*重新连接，连接失败返回-           2，成功返回sockfd的值*/                                    
		{
			if( sampling )    /*采了数据但是连接断开了*/
			{
				log_info("Insert data into client sqlite...\n");
				database_safe_insert(&data);
			}
			continue;
		}

		/*  检查连接状态的时候是连接的*/
		if( sampling ) 
		{
			log_info("sent data to server...\n");

			if( socket_write(&sock, buf, len) <0)
			{
				log_info("write failure\n");
				continue;
			}
		}	
		
		if( database_1st_record(&data) )
		{
			log_info("sqlite database have data!will sent...\n");
			
			if(database_send_data(&sock, &data))
			{
				log_warn("synchronization failure\n");
				continue;
			}

			if( database_delete_1st(&data))
			{
				log_info("synchronization secessful!\n");
			}
		}

		sleep(1);
	}

Cleanup:
	database_term();
	close(sock.sockfd);
	logger_term();
	unlink(PIDFILE);

	return 0;
}

void stop(int signum)
{
	(void)signum;
	pro_stop = 1;
}

